#include "map.h"
#include "math.h"
#include <QDebug>
Map::Map(qreal x, qreal y, qreal w, qreal h, QObject* parent) :
	QGraphicsScene(parent) {
	setBoundingRect(QRectF(x, y, w, h));
	setSceneRect(QRectF(x, y, w, h));
	addObstacle(QVector<QPointF>() << QPointF(-100,-100) << QPointF(0,-100) << QPointF(0,0) << QPointF(-100,0));
	//addObstacle(QVector<QPointF>() << QPointF(-400, 400) << QPointF(-400,200) << QPointF(400,200) << QPointF(400,400));
	addSpawPoint(QPointF(50,50));
	addSpawPoint(QPointF(x+10,y+10));
	addSpawPoint(QPointF(x-10+w,y+10));
	addSpawPoint(QPointF(x+10,y-10+h));
	addSpawPoint(QPointF(x-10+w,y-10+h));


	start_x = x;
	start_y = y;
	pheight = h;
	pwidth = w;
	players.clear();
	timer = new QTimer();
	connect(timer, SIGNAL(timeout()), this, SLOT(updateMap()));
	timer->start(20);
}

void Map::addObstacle(QVector<QPointF> points) {
	QPolygonF * poly = new QPolygonF();

	for (int i = 0; i < points.count(); i++) {
		poly->append(points.at(i));
	}
	QPen pen;
	QBrush brush;

	brush.setStyle(Qt::Dense6Pattern);

	addPolygon(*poly, pen, brush)->setZValue(2);
}

void Map::setBoundingRect(QRectF r) {
	qreal x1, x2, y1, y2;
	r.getCoords(&x1, &y1, &x2, &y2);
	addObstacle(QVector<QPointF> () << QPointF(x1, y1) << QPointF(x2, y1));
	addObstacle(QVector<QPointF> () << QPointF(x2, y1) << QPointF(x2, y2));
	addObstacle(QVector<QPointF> () << QPointF(x2, y2) << QPointF(x1, y2));
	addObstacle(QVector<QPointF> () << QPointF(x1, y2) << QPointF(x1, y1));
}

void Map::onHitPlayer(Player* p1, Player* p2)
{
	qDebug() << "map emit hit";
	emit hitPlayer(p1,p2);
}

void Map::addPlayer(Player* player, bool isRemote, Mouse* mouse) {

	players.append(player);
	player->setGun(new Gun());
	addItem(player);
	if (!isRemote) {
		//player->grabKeyboard();
		player->setGun(new Gun());
		player->setMouse(mouse);
	}
	connect(player, SIGNAL(hitPlayer(Player*, Player*)), this, SLOT(onHitPlayer(Player*, Player*)));
}

void Map::removePlayers()
{
	foreach (Player*p , players)
	{
		QVector<Bullet*> bullets = p->getBullets();
		foreach (Bullet*b , bullets)
		{
			//removeItem(b);
			delete b;
		}
		//removeItem(p);
		delete p;
	}
	players.clear();
}

void Map::addSpawPoint(QPointF point) {
	spawPoints.append(point);
}

void Map::spawnPlayers()
{
	foreach (Player* player, players)
	{
		if (!player->getIsAlive())
		{
			quint32 now = time(0);
			if (now - player->getDeathTime() > 4)
			{
				qDebug() << "player spawned";

				if (player->getIsRemote())
				{
					player->getConnectionPlayer()->setIsAlive(true);
					qDebug() << "setting connplayer position";
					QPointF rp = spawPoints.at(rand() % (spawPoints.count()));
					qDebug() << rp;
					player->getConnectionPlayer()->setPosition(rp);
				}
				else
				{
					player->changePos(spawPoints.at(rand() % (spawPoints.count())));
					player->setIsAlive(true);
				}
			}
		}
	}
}

void Map::updateMap() {
	for (int i = 0; i < players.count(); i++) {
		Player* p = players.at(i);
		if (p->getIsAlive()) {
			if (p->movePlayer()) {

				collidePlayer(p);
			}
			QVector<Bullet*> bullets = p->getBullets();
			for (int j = 0; j < bullets.count(); j++) {
				Bullet* b = bullets.at(j);

				b->moveBullet();
				b->acceptPos();

			}
		}

	}

	update(boundingRect());
}

void Map::collidePlayer(Player* player) {
	Collision coll;
	int i = 0;
	while (coll.getPolygonCollisionCount(player) > 0 && i <= 10) {
		coll.checkCollision(player);
		i++;
	}
	if (i > 10)//gracz sie zaklinowal, powrot do poprzedniej bezpiecznej pozycji
	{
		player->revertPos();
	} else {
		player->acceptPos();
	}
}

QRectF Map::boundingRect() {
	return QRectF(start_x, start_y, pwidth, pheight);
}
